package com.newmuis.open.codeeval.easy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * CodeEval.com > Easy Challenges > Fizz Buzz
 * 
 * Description:
 * Players generally sit in a circle. The player designated to go first says the number "1", and
 * each player thenceforth counts one number in turn. However, any number divisible by 'A' e.g.
 * three is replaced by the word fizz and any divisible by 'B' e.g. five by the word buzz. Numbers
 * divisible by both become fizz buzz. A player who hesitates or makes a mistake is either
 * eliminated.
 * 
 * Write a program that prints out the the pattern generated by such a scenario given the values of
 * 'A'/'B' and 'N' which are read from an input text file. The input text file contains three space
 * delimited numbers i.e. A, B, N. The program should then print out the final series of numbers
 * using 'F' for fizz, 'B' for 'buzz' and 'FB' for fizz buzz.
 * 
 * Input sample:
 * 
 * Your program should read an input file (provided on the command line) which contains multiple
 * newline separated lines. Each line will contain 3 numbers which are space delimited. The first
 * number is first number to divide by ('A' in this example), the second number is the second number
 * to divide by ('B' in this example) and the third number is where you should count till ('N' in
 * this example). You may assume that the input file is formatted correctly and is the numbers are
 * valid positive integers.e.g.
 * 
 * 3 5 10
 * 2 7 15
 * 
 * Output sample:
 * 
 * Print out the series 1 through N replacing numbers divisible by 'A' by F, numbers divisible by
 * 'B' by B and numbers divisible by both as 'FB'. Since the input file contains multiple sets of
 * values, your output will print out one line per set. Ensure that there are no trailing empty
 * spaces on each line you print.e.g.
 * 
 * 1 2 F 4 B F 7 8 F B
 * 1 F 3 F 5 F B F 9 F 11 F 13 FB 15
 * 
 * @author Jonathan Newmuis (jon@newmuis.com)
 * @category easy
 */
public class fizzbuzz {

	/**
	 * Prints out the output in the defined "fizz buzz" format to {@link System.out}.
	 * 
	 * @param a The first number to divide by.
	 * @param b The second number to divide by.
	 * @param n The number to count to.
	 */
	private static void printFizzBuzz(final int a, final int b, final int n) {
		final StringBuilder resultBuilder = new StringBuilder();
		for (int i = 1; i <= n; i++) {
			// Determine which element should be output ("F", "B", "FB", or the integer).
			if (i % a == 0 && i % b == 0) {
				resultBuilder.append("FB");
			} else if (i % a == 0) {
				resultBuilder.append("F");
			} else if (i % b == 0) {
				resultBuilder.append("B");
			} else {
				resultBuilder.append(i);
			}

			// Append a space, only if not yet reached final element.
			if (i < n) {
				resultBuilder.append(" ");
			}
		}

		// Output builder contents.
		System.out.println(resultBuilder.toString());
	}

	/**
	 * @param args should contain only one CLI argument: the path to an input file which specifies
	 *            the input in the defined format.
	 * @throws IOException if there is a problem reading the given input file.
	 */
	public static void main(final String[] args) throws IOException {
		// Verify input argument length.
		if (args.length < 1) {
			throw new RuntimeException("Must specify input file path.");
		} else if (args.length > 1) {
			throw new RuntimeException("Illegal input arguments specified.");
		}

		// Read file from specified path.
		final BufferedReader reader = new BufferedReader(new FileReader(new File(args[0])));
		String line;

		while ((line = reader.readLine()) != null) {
			// Parse the arguments.
			final String[] fizzBuzzArgs = line.split("\\s");

			// Verify the length of the "fizz buzz" arguments given in the input file.
			if (fizzBuzzArgs.length != 3) {
				throw new RuntimeException("Input file must contain three arguments per line.");
			}

			try {
				// Print the "fizz buzz" output sequence.
				final int a = Integer.parseInt(fizzBuzzArgs[0]);
				final int b = Integer.parseInt(fizzBuzzArgs[1]);
				final int n = Integer.parseInt(fizzBuzzArgs[2]);
				printFizzBuzz(a, b, n);
			} catch (final NumberFormatException e) {
				throw new RuntimeException("Input file contained non-numeric arguments.");
			}
		}
	}

}
